package com.polaris.live.ui.live.fragment

import android.app.Activity
import android.os.Bundle
import android.view.View
import androidx.core.os.bundleOf
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.Utils
import com.gyf.immersionbar.ImmersionBar
import com.lxj.xpopup.XPopup
import com.polaris.live.R.drawable
import com.polaris.live.cache.CommonCache
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.ext.convertArabicDigitsToNormal
import com.polaris.live.common.ext.formatNumberWithK
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.mvvm.base2.BaseVbFragment
import com.polaris.live.common.network.parseState
import com.polaris.live.common.util.DateUtils
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.NavigationBarUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.common.util.ViewUtils
import com.polaris.live.constant.LiveConst
import com.polaris.live.constant.UserConst
import com.polaris.live.databinding.FragmentJustLiveBinding
import com.polaris.live.dialog.AwardProgressDialog
import com.polaris.live.dialog.GlobalDialogManager
import com.polaris.live.dialog.LiveHangUpDialog
import com.polaris.live.dialog_fragment.RoomInvitationFragmentDialog
import com.polaris.live.dialog_fragment.magiclamp.MagicLampPopup
import com.polaris.live.im.manager.ImLiveManager
import com.polaris.live.im.manager.OnLiveObserveListener
import com.polaris.live.im.manager.RouterControlManager
import com.polaris.live.im.sfs.BIG_BROTHER_ENTERS_ROOM
import com.polaris.live.im.sfs.COMMAND_LIVE_CLOSE
import com.polaris.live.im.sfs.COMMAND_LIVE_FLOATING
import com.polaris.live.im.sfs.COMMAND_LIVE_NOTICE
import com.polaris.live.im.sfs.LIVE_MAGIC_LAMP_90
import com.polaris.live.im.sfs.LIVE_MAGIC_LAMP_OPEN
import com.polaris.live.im.sfs.LIVE_NEW_ANCHOR
import com.polaris.live.im.sfs.LIVE_PUBLIC_SCREEN
import com.polaris.live.im.sfs.LIVE_SEND_GIFT
import com.polaris.live.im.sfs.LIVE_UPLOAD_FACE
import com.polaris.live.im.sfs.LIVE_WARN_MESSAGE
import com.polaris.live.im.sfs.LUCKY_BACKPACK_GIFT
import com.polaris.live.im.sfs.bean.live.CallSignalingMessage
import com.polaris.live.im.sfs.bean.live.LivePublicScreenMessage
import com.polaris.live.im.sfs.bean.live.LiveRoomInfo
import com.polaris.live.im.sfs.bean.live.SendLiveCloseMessage
import com.polaris.live.im.sfs.bean.live.SendLiveFloatingMessage
import com.polaris.live.im.sfs.bean.live.SendLiveNoticeMessage
import com.polaris.live.im.sfs.bean.live.ext.LiveEnterBean
import com.polaris.live.im.sfs.bean.live.ext.MessageUserExtBean
import com.polaris.live.im.sfs.bean.live.ext.UserBasicVo
import com.polaris.live.im.sfs.bean.live.payload.InviteGiftPayloadBean
import com.polaris.live.im.sfs.bean.live.payload.LiveNoticePayloadBean
import com.polaris.live.im.sfs.bean.live.payload.NewAnchorSubsidyPayloadBean
import com.polaris.live.im.utils.SmartFoxUtils.parseVariables
import com.polaris.live.manager.AppConfigManager
import com.polaris.live.manager.LiveStateManager
import com.polaris.live.popup.ContributionListPopup
import com.polaris.live.popup.GameListPopup
import com.polaris.live.popup.GlobalPopupManager
import com.polaris.live.popup.MagicLampWinRewardPopup
import com.polaris.live.popup.VipBarrageWhatPopup
import com.polaris.live.popup.WeeklyStarPopup
import com.polaris.live.resp.back_resp.InfoOtherResp
import com.polaris.live.resp.back_resp.LiveSubsidyIndicatorResp
import com.polaris.live.resp.back_resp.ScreenshotStrategyVo
import com.polaris.live.resp.back_resp.toUserBasicVo
import com.polaris.live.resp.bean.MagicLampCountDownBean
import com.polaris.live.resp.event.BackgroundEvent
import com.polaris.live.translation.R.string
import com.polaris.live.ui.game.GameUtils
import com.polaris.live.ui.live.proxy.LiveMoreProxy
import com.polaris.live.ui.live.proxy.LivePublicProxy
import com.polaris.live.ui.live.proxy.gift.EntryScreenAnimationProxy
import com.polaris.live.ui.live.proxy.gift.GiftAnimationProxy
import com.polaris.live.ui.live.widget.LiveFloatView
import com.polaris.live.ui.live.widget.OnLiveAnswerListener
import com.polaris.live.ui.live.widget.listener.OnBackPressedListener
import com.polaris.live.ui.live.widget.listener.OnChangeCameraListener
import com.polaris.live.ui.live.widget.listener.OnLiveCallCallback
import com.polaris.live.ui.live.widget.listener.OnLiveEventListener
import com.polaris.live.ui.live.widget.listener.OnLiveNetworkListener
import com.polaris.live.ui.live.widget.listener.OnLiveStateSwitchListener
import com.polaris.live.ui.live.widget.listener.OnSendPublicMessageListener
import com.polaris.live.ui.main.live.LiveFragment
import com.polaris.live.ui.message.fragment.MessageSessionFragment
import com.polaris.live.ui.message.fragment.dialog.MessageSessionDialogFragment
import com.polaris.live.ui.message.fragment.dialog.MessageSingleDialogFragment
import com.polaris.live.ui.party.utils.BigBrotherEntersTheArenaProxy
import com.polaris.live.utils.LiveUtils
import com.polaris.live.utils.TaskRedListener
import com.polaris.live.utils.TaskRedProxy
import com.polaris.live.utils.XPopupUtils
import com.polaris.live.utils.autoFragmentHide
import com.polaris.live.utils.file.FileUtils
import com.polaris.live.utils.fragment.showNewDialogFragment
import com.polaris.live.utils.route.RoutePath
import com.polaris.live.utils.route.Router
import com.polaris.live.utils.zego.LiveEngineManage
import com.polaris.live.utils.zego.beauty.OnFaceStateChangeListener
import com.polaris.live.viewmodel.live.LiveVideoViewModel
import im.zego.zegoexpress.callback.IZegoEventHandler
import im.zego.zegoexpress.entity.ZegoPlayStreamQuality
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import sfs2x.client.core.SFSEvent
import sfs2x.client.entities.variables.RoomVariable
import java.io.File

/**
 * 直播页面
 *
 * @author Created by lucas on 2023/11/10 17:02
 * @since 1.0.0
 */
class LiveVideoFragment : BaseVbFragment<LiveVideoViewModel, FragmentJustLiveBinding>(),
    OnBackPressedListener,
    OnLiveStateSwitchListener,
    OnFaceStateChangeListener,
    OnLiveEventListener,
    OnLiveNetworkListener,
    OnChangeCameraListener {

    private val mLiveInfo by lazy {
        arguments?.getParcelable<LiveRoomInfo>(LiveConst.Params.LIVE_INFO)
            ?: throw IllegalArgumentException("liveInfo is null")
    }
    private val mScreenshotStrategy by lazy {
        arguments?.getParcelable<ScreenshotStrategyVo>(LiveConst.Params.SCREENSHOT_STRATEGY)
    }

    private val mSessionFragment by lazy { MessageSessionDialogFragment() }

    //被禁言的人
    private val mBanMessageUser = mutableListOf<Long>()

    private val mLiveMoreProxy by lazy {
        LiveMoreProxy(
            requireContext(), this, mViewModel,
            pageType,
            this,
            this
        )
    }

    //礼物代理
    private var mGiftProxy: GiftAnimationProxy? = null

    /**
     * 进场动效
     */
    private var mEntryScreenAnimationProxy: EntryScreenAnimationProxy? = null
    private val mLivePublicProxy by lazy {
        LivePublicProxy(requireContext(), mViewModel)
    }

    private val mBigBrotherEntersTheArenaUtils by lazy {
        BigBrotherEntersTheArenaProxy(mBinding.gifta, this)
    }

    private var mOnLiveCallCallback: OnLiveCallCallback? = null
    private var mOnLiveAnswerListener: OnLiveAnswerListener? = null

    private var mPauseLiving: Boolean = false
    private var mStopLive: Boolean = false

    private var mSubsidy: LiveSubsidyIndicatorResp? = null

    private var lastIndex = 3

    private val mEventHandler = object : IZegoEventHandler() {
        override fun onPlayerQualityUpdate(streamID: String?, quality: ZegoPlayStreamQuality?) {
            super.onPlayerQualityUpdate(streamID, quality)
            if (quality?.level in LiveStateManager.USER_LIVE_STATE_BAD) {
                mBinding.llSignal.visibility = View.VISIBLE
            } else {
                mBinding.llSignal.visibility = View.GONE
            }
        }
    }

    private fun initImmersionBar() {
        ImmersionBar.with(this)
            .transparentBar()
            .titleBarMarginTop(mBinding.rlContent)
            .init()

        NavigationBarUtils.setNavigationHeight(mBinding.rlContent)
        NavigationBarUtils.setNavigationHeight(mBinding.vFooter)
    }

    override fun initView(savedInstanceState: Bundle?) {
        initImmersionBar()

        EventBus.getDefault().register(this)
        LiveEngineManage.eventHandlerHelper.addEventHandler(mEventHandler)

        //UI初始化
        mBinding.apply {
            vFooter.attachEditView(mBinding.vEdit)

            vHeader.initData(pageType, mLiveInfo, 1)
            vMessage.initData(pageType, mLiveInfo)
            vFooter.initUI(pageType, mViewModel)
            vFooter.initData(mLiveInfo)
            vEdit.initData(mLiveInfo)
            contributionView.showGainCoins(mLiveInfo.showGainCoins?.formatNumberWithK() ?: "0")
            vHeader.updateUserCount(mLiveInfo.joinCount)
            CommonCache.getMagicLampList().forEach { widgetMagicLamp.addMagicLampPag(it) }
        }
        val liveResource = CommonCache.getLiveResource()
        if (liveResource != null) {
            when (liveResource.liveSubsidy) {
                LiveFragment.SUBSIDT_SHOW -> mBinding.ivLookAnchor.visibility = View.GONE
                LiveFragment.SUBSIDY_OPEN -> mBinding.ivLookAnchor.visibility = View.VISIBLE
                LiveFragment.SUBSIDY_CLOSE -> mBinding.ivLookAnchor.visibility = View.VISIBLE
            }
        } else {
            mBinding.ivLookAnchor.visibility = View.GONE
        }

        mViewModel.getSubsidy()
        mGiftProxy = UserManager.getUser().nickname?.let {
            GiftAnimationProxy(this, requireActivity(), mBinding.llGift, it).apply {
                //礼物队列点击头像
                setOnHeadOnClickListener {
                    showUserProfilePopup(it)
                }
            }
        }
        mEntryScreenAnimationProxy =
            EntryScreenAnimationProxy(
                requireActivity(),
                mBinding.entryFloatingScreen,
                mBinding.entryScreen,
                viewLifecycleOwner
            )

        initListener()
        initObserver()
        mBinding.widgetRoomBanner.initBannerData(lifecycle, mViewModel, mLiveInfo.liveId, mLiveInfo.userId)
        mBinding.actMarquee.getActivitiesScroll(mViewModel, mLiveInfo.userId)
        setSkinUi()
    }

    //点击监听
    private fun initListener() {
        mBinding.apply {
            /**
             * 展示详情弹窗
             */
            weekStar.setShowDetail {
                WeeklyStarPopup.showPop(requireContext(), this@LiveVideoFragment, mViewModel, lastIndex) {
                    lastIndex = it
                }
            }
            /**
             * 周星是否显示数据
             */
            weekStar.setShowWeekStarCallBack {
                if (it) {
                    mViewModel.pollingWeeklyStarRank()
                } else {
                    mViewModel.cancelPollingWeeklyStarRank()
                }
            }

            //直播间用户列表
            vHeader.setOnConsumeItemClickListener { _, item ->
                showUserProfilePopup(item.userId)
            }
            //点击主播头像
            vHeader.setOnAvatarClientListener {
                showUserProfilePopup(mLiveInfo.userId)
            }
            //显示头像
            vMessage.getMessageView().setOnUserProfileClickListener {
                showUserProfilePopup(it)
            }
            //公屏举报
            vMessage.getMessageView().setOnReportListener {
                if (it.ext is MessageUserExtBean) {
                    GlobalPopupManager.showReport(
                        requireContext(), it.ext.user.nickname,
                        mViewModel, it.ext.user.userId, mLiveInfo.liveId
                    )
                }
            }
            //直播间飘屏被点击
            widgetFloat.setOnSingleClickListener { data ->
                when (data.type) {
                    LiveFloatView.GAME -> { //游戏中奖
                        GameUtils.showAndCheckGameFragment(
                            requireContext(),
                            mLiveInfo.userId,
                            data.payload
                        )
                    }
                }
            }
            vEdit.setOnSendPublicMessageListener(object : OnSendPublicMessageListener {
                override fun onSendPublicMessage(message: LivePublicScreenMessage) {
                    mViewModel.sendPublicMessage(message)
                }

                override fun onBarrageWhat() {
                    VipBarrageWhatPopup.showPop(requireContext(), false) {
                        Router.instance.setPath(RoutePath.VIP_CENTER_ACTIVITY)
                            .withInt("page", 0)
                            .withInt("level", 6)
                            .navigation(requireContext())
                    }
                }
            })
            vFooter.setOnMessageClickListener {
                mSessionFragment.show(
                    childFragmentManager,
                    MessageSessionDialogFragment.FRAGMENT_TAG
                )
            }
            vFooter.setOnGameClickListener {
                GameListPopup.show(
                    requireContext(),
                    GameUtils.getLiveCacheGameList(),
                    mLiveInfo.userId.toString()
                )
            }
            vFooter.setOnMoreClickListener {
                mLiveMoreProxy.showVideoMore(
                    objectId = mLiveInfo.liveId,
                    onKeyboardStateListener = {
                        mBinding.vEdit.setKeyboardListerState(it)
                    },
                    mIsOpenGift = mBinding.widgetGift.getIsOpenGift(),
                    mIsOpenSound = mBinding.widgetGift.getIsOpenSound(),
                    onOpenGiftAnimation = {
                        mBinding.widgetGift.setIsOpenGiftAnimation(it)
                        mBinding.widgetMagicLamp.setIsOpenGiftAnimation(it)
                    }, onOpenGiftSound = {
                        mBinding.widgetGift.setIsOpenSound(it)
                    }, onInvitationFriend = {
                        val fragmentManager = childFragmentManager
                        RoomInvitationFragmentDialog().apply {
                            arguments = bundleOf("liveId" to mLiveInfo.liveId)
                        }.show(
                            fragmentManager,
                            "RoomInvitationFragmentDialog"
                        )
                    }
                )
            }
            avAnswer.setOnLiveAnswerListener(object : OnLiveAnswerListener {
                override fun onAnswer(message: CallSignalingMessage, needLoading: Boolean) {
                    mOnLiveAnswerListener?.onAnswer(message, needLoading)
                }

                override fun onRefuse(message: CallSignalingMessage, type: Int) {
                    mOnLiveAnswerListener?.onRefuse(message, type)
                }
            })
            ivLookAnchor.setOnSingleClickListener {
                mViewModel.getSubsidy()
            }
            //点击隐藏edit
            ViewUtils.registerTouchDown(mBinding.vShade) {
                mBinding.vEdit.hideKeyboard()
            }
            //用户在线列表
            vHeader.setOnOnlineClickListener {
                GlobalPopupManager.showOnlineUser(
                    requireContext(), this@LiveVideoFragment, mViewModel,
                    mLiveInfo.liveId, mLiveInfo.userId, LiveConst.Type.LIVE_AND_MATCH,
                    onHeadClickListener = {
                        showUserProfilePopup(it)
                    },
                    onSendGiftSomeOneCallback = {
                        it ?: return@showOnlineUser
                        mSessionFragment.show(
                            childFragmentManager,
                            MessageSessionDialogFragment.FRAGMENT_TAG
                        )
                        childFragmentManager.showNewDialogFragment(
                            MessageSingleDialogFragment(
                                it.userId,
                                it.avatar,
                                it.avatarFrame,
                                it.chatBubble,
                                false
                            ), MessageSessionFragment.FRAGMENT_TAG
                        )
                    }
                )
            }
            /**
             * 点击贡献榜
             */
            contributionView.setOnSingleClickListener {
                ContributionListPopup.showPop(
                    requireContext(),
                    this@LiveVideoFragment,
                    mViewModel,
                    UserManager.getUserId()
                ) {
                    mSessionFragment.show(
                        childFragmentManager,
                        MessageSessionDialogFragment.FRAGMENT_TAG
                    )
                    childFragmentManager.showNewDialogFragment(
                        MessageSingleDialogFragment(
                            it.user.userId,
                            it.user.avatar,
                            it.user.avatarFrame,
                            it.user.chatBubble,
                            false
                        ), MessageSessionFragment.FRAGMENT_TAG
                    )
                }
            }
            widgetRoomBanner.setMagicLampListener {
                mLiveInfo.let { info ->
                    MagicLampPopup.show(this@LiveVideoFragment, mViewModel, info.userId, true) {}
                }

            }
            barrageView.addReportCallBack {
                GlobalPopupManager.showReport(
                    requireContext(),
                    it.nickname,
                    mViewModel,
                    it.userId,
                    it.userId
                )
            }
        }
    }

    private val onAppStatusChangedListener = object : Utils.OnAppStatusChangedListener {
        override fun onForeground(activity: Activity?) {
            mViewModel.stopKillActivityTimeout()
        }

        override fun onBackground(activity: Activity?) {
            mViewModel.killActivityTimeout(maxBackgroundTime)
        }
    }

    private fun initObserver() {
        AppUtils.registerAppStatusChangedListener(onAppStatusChangedListener)
        /**
         * 周星数据更新
         */
        mViewModel.weeklyStarRankData.observe(this) { state ->
            parseState(state, {
                if (it.show) {
                    mViewModel.cancelPollingWeeklyStarRank()
                    mBinding.weekStar.visibility = View.VISIBLE
                    it.base?.let { da ->
                        mBinding.weekStar.setData(da)
                    }
                } else {
                    mViewModel.pollingWeeklyStarRank()
                    mBinding.weekStar.visibility = View.GONE
                }
            }, {
                //报错开启定时请求
                mViewModel.pollingWeeklyStarRank()
            })
        }
        //停止直播
        mViewModel.stopLiveLiveData.observe(this) { state ->
            parseState(state, {
                Router.builder(RoutePath.LIVE_END_ANCHOR_ACTIVITY)
                    .withInt(LiveConst.Params.LIVE_TYPE, mLiveInfo.type)
                    .withAny(LiveConst.Params.LIVE_END_INFO, it)
                    .navigation(requireActivity())
            }, {
                ToastGravity.showGravity(it.message)
            })
            requireActivity().finish()
        }
        //恢复直播间失败
        mViewModel.recoverFailureLiveData.observe(this) {
            onStopLive()
        }
        //获取游戏列表
        mViewModel.gameLiveData.observe(this) { resultState ->
            parseState(resultState, {
                mBinding.vFooter.updateGameState(it.isNotEmpty())
                GameUtils.setLiveCacheGameList(it)
            })
        }
        //直播获取顶部消费列表
        mViewModel.liveConsumeLiveData.observe(this) { (liveId, it) ->
            if (mLiveInfo.liveId == liveId) {
                mBinding.vHeader.updateConsumeList(it)
                mBinding.widgetRoomBanner.upDataMagicLamp()
            }
        }
        //活动滚动信息刷新
        mViewModel.activitiesScrollLiveData.observe(this) {
            mLiveInfo.let { info ->
                mBinding.actMarquee.getActivitiesScroll(mViewModel, info.userId)
            }
        }
        //直播间人数定时刷新
        mViewModel.liveUserCountLiveData.observe(this) {
            mBinding.vHeader.updateUserCount(it - 1)
        }
        //人脸
        mViewModel.faceStateLiveData.observe(this) {
            if (mLiveInfo.type == LiveConst.Type.ONLY_LIVE) return@observe
            if (it == -2) {
                onStopLive()
            } else if (it == -1) {
                mBinding.llDark.visibility = View.GONE
            } else {
                mBinding.llDark.visibility = View.VISIBLE
                mBinding.icBotton.text = "${it / 1000}"
            }
        }
        //心跳
        mViewModel.liveHeartbeatLiveData.observe(this) {
            if (it) {
                onStopLive()
            }
        }
        //计时
        mViewModel.timerLiveData.observe(this) {
            val millis2String = DateUtils.minuteSChangeTime(it)
            mBinding.trialTime.text = "${millis2String.convertArabicDigitsToNormal()}"
            mBinding.llTrial.visibility = View.VISIBLE
        }
        //试播
        mViewModel.trialCountdownLiveData.observe(this) {
            if (it == -1L) {
                mBinding.llTrial.visibility = View.GONE
                mBinding.timerImg.setImageResource(drawable.ic_timer)
                mViewModel.timerdown(mLiveInfo.startTime)
            } else {
                val millis2String = TimeUtils.millis2String(it, "mm:ss")
                mBinding.trialTime.text =
                    "${StringUtils.getString(string.trail_time)} ${millis2String.convertArabicDigitsToNormal()}"
                mBinding.llTrial.visibility = View.VISIBLE
            }
        }

        mViewModel.mSubsidyLiveData.observe(this) { resultState ->
            parseState(resultState, {
                if (mSubsidy == null) {
                    mSubsidy = it
                } else {
                    mSubsidy = it
                    if (it.show) {
                        XPopup.Builder(requireContext())
                            .isDestroyOnDismiss(true)
                            .asCustom(AwardProgressDialog(requireContext(), it))
                            .show()
                    } else {
                        mBinding.ivLookAnchor.visibility = View.GONE
                    }
                }
            })
        }
        //直播关闭消息，如果直播接收到消息，说明服务器关闭了直播
        ImLiveManager.observe(this, { mLiveInfo.liveId }) {
            withMessage<SendLiveCloseMessage>(COMMAND_LIVE_CLOSE) {
                onStopLive()
            }
        }
        //飘屏消息
        ImLiveManager.observe<SendLiveFloatingMessage>(
            this,
            COMMAND_LIVE_FLOATING,
            { OnLiveObserveListener.ANY_ID }) {
            mBinding.widgetFloat.addFloatView(it)
        }
        //直播间通知消息
        ImLiveManager.observe<SendLiveNoticeMessage>(
            this,
            COMMAND_LIVE_NOTICE,
            { OnLiveObserveListener.ANY_ID }
        ) {
            val payload = it.payload ?: return@observe
            val fromJson = JsonUtils.fromJson<LiveNoticePayloadBean>(payload)
            //如果是pag 就判断是否下载过了
            if (fromJson?.titleImageType == LiveConst.NoticeImageType.PAG) {
                val path =
                    FileUtils.getFilePath(FileUtils.getPagFile(), it.titleImage)
                if (File(path).exists()) {
                    GlobalDialogManager.showLiveNotice(requireContext(), it)
                } else {
                    mViewModel.downLoadPag(it)
                }
            } else {
                GlobalDialogManager.showLiveNotice(requireContext(), it)
            }
        }
        //直播用户加入消息
        ImLiveManager.observeEvent(this) { command, argument ->
            when (command) {
                SFSEvent.USER_ENTER_ROOM -> {
                    val user = argument.getUser()
                    if (user == null || user.name == UserManager.getUserId().toString()) {
                        return@observeEvent
                    }
                    argument.getUser()?.parseVariables<LiveEnterBean>()?.let {
                        mEntryScreenAnimationProxy?.addEntryScreenOtherUser(it) {
                            mBinding.vEnter.addEnterBean(it)
                        }
                    }
                }

                SFSEvent.USER_EXIT_ROOM -> {
                    val user = argument.getUser()
                    if (user == null || user.name == UserManager.getUserId().toString()) {
                        return@observeEvent
                    }
                    mEntryScreenAnimationProxy?.removeEntryScreen(user.name.toLong())

                }
                //如果是加入则刷新直播间的信息
                SFSEvent.ROOM_JOIN -> {
                    argument.getRoom()?.also { room ->
                        room.variables.forEach {
                            variableUpdate(it)
                        }
                    }
                }
            }
        }

        //直播公屏消息
        ImLiveManager.observePublicMessage(this, { mLiveInfo.liveId }, { message ->
            //多加一层判断，因为有可能刚把消息放过来，就切换了状态  导致  新的状态也接收了这个公屏消息
            if (message.type in ImLiveManager.publicTypes && message.businessId == mLiveInfo.liveId) {
                mBinding.vMessage.addMessage(message)
                if (message.type == LIVE_PUBLIC_SCREEN) {
                    val ext = message.ext as? MessageUserExtBean?
                    if (ext?.type == 1) { //发送的弹幕消息
                        mBinding.barrageView.addMessage(message)
                    }
                }
            }

            //其他消息处理
            when (message.type) {
                //人脸上报
                LIVE_UPLOAD_FACE -> {
                    mViewModel.facesDetect(mLiveInfo.liveId)
                }
                //发送公屏消息
                LIVE_SEND_GIFT, LUCKY_BACKPACK_GIFT -> {
                    mGiftProxy?.addAnimation(message)
                    val payload = message.payload as InviteGiftPayloadBean
                    payload.gift.animation?.let { mBinding.widgetGift.setGift(payload) }
                }

                //警告消息
                LIVE_WARN_MESSAGE -> {
                    mLivePublicProxy.onPublicMessage(message)
                }

                //新主播补贴消息
                LIVE_NEW_ANCHOR -> {
                    val payload = message.payload as NewAnchorSubsidyPayloadBean
                    GlobalDialogManager.showNewLiveAnchor(requireContext(), payload)
                }
                //大哥进场
                BIG_BROTHER_ENTERS_ROOM -> {
                    mBigBrotherEntersTheArenaUtils.addData(message)
                }
                //神灯进度90%
                LIVE_MAGIC_LAMP_90 -> {
                    mBinding.widgetRoomBanner.upDataMagicLamp()
                }
                //神灯开奖
                LIVE_MAGIC_LAMP_OPEN -> {
                    val payload = message.payload as MagicLampCountDownBean
                    mBinding.widgetRoomBanner.upDataMagicLamp()
                    mBinding.widgetMagicLamp.addMagicLampPag(payload)
                }
            }
        })
        //直播变量变化
        ImLiveManager.observeVariableUpdate(this, { mLiveInfo.userId }, {
            variableUpdate(it)
        })
        //直播人数变化
        ImLiveManager.observeUserCountChange(this, { mLiveInfo.userId }, {
            mBinding.vHeader.updateUserCount(it - 1)
        })
        //pag下载
        mViewModel.mDownLoadLiveData.observe(this) {
            GlobalDialogManager.showLiveNotice(requireContext(), it)
        }
        TaskRedProxy.observe(this, object : TaskRedListener {
            override fun updateRed(isRed: Boolean) {
                mBinding.vFooter.setMoreRed(if (isRed) View.VISIBLE else View.GONE)
            }
        })
        //路由监听
        RouterControlManager.observeListener(this) { key, ext ->
            withLoaded {
                when (key) {
                    RouterControlManager.ROUTER_ROOMGAME -> { //打开幸运游戏列表
                        val gameId = ext["gameId"]?.toLongOrNull()
                        if (gameId == null) {
                            showGameList()
                        } else {
                            val gameVo = GameUtils.getLiveCacheGameList()
                                ?.asSequence()
                                ?.flatMap { it.list.asSequence() }
                                ?.find { it.gameID == gameId }
                            if (gameVo != null) {
                                val roomId = mLiveInfo.userId.toString()
                                GameUtils.showGameFragment(requireContext(), gameVo, roomId = roomId)
                            } else {
                                showGameList()
                            }
                        }
                    }

                    RouterControlManager.ROUTER_GIFT -> { //礼物盘拉起
                        val giftType = ext["giftType"]?.toIntOrNull()
                        mBinding.vFooter.showGiftDialog(null, giftType = giftType ?: -1)

                    }
                }
            }
        }
        mViewModel.mLampLotteryLiveData.observe(this) { resultState ->
            parseState(resultState, {
                MagicLampWinRewardPopup.show(requireContext(), it)
            }) {
                ToastGravity.showGravity(it.errorMsg)
            }
        }
        mBinding.widgetMagicLamp.openMagicLampCallBack {
            mLiveInfo.userId.let { userId ->
                mViewModel.lampLottery(userId, it.index.toLong())
            }
        }
        //更新弹幕信息
        mViewModel.barrageNumberLiveData.observe(this) { resultState ->
            parseState(resultState, {
                mBinding.vEdit.upBarrage(it)
            })
        }
    }

    private fun showGameList() {
        val roomId = (mLiveInfo.userId ?: "").toString()
        GameListPopup.show(requireContext(), GameUtils.getLiveCacheGameList(), roomId)
    }

    private fun variableUpdate(variable: RoomVariable) {
        LiveUtils.fillLiveInfo(mLiveInfo, variable)

        when (variable.name) {
            "showGainCoins" -> {
                mBinding.contributionView.showGainCoins(mLiveInfo.showGainCoins?.formatNumberWithK() ?: "0")
            }

            "banMessageUser" -> {
                mBanMessageUser.clear()
                mLiveInfo.banMessageUser?.let { banMessageUserJson ->
                    val data: List<Long>? = JsonUtils.fromJson(banMessageUserJson)
                    data?.let {
                        mBanMessageUser.addAll(it)
                    }
                }
            }

            "roomTheme" -> {
                setSkinUi()
            }
        }
    }

    override fun initData() {
        mViewModel.getGameList(mLiveInfo.liveId)  //游戏列表

        //默认总是直播所以这里可以直接开始
        onLiveResume()
    }

    override fun onLivePause() {
        withLoaded {
            invokeOnLivePause()
        }

        mPauseLiving = true
    }

    private fun invokeOnLivePause() {
        mViewModel.resetLiveJob()
    }

    override fun onLiveResume() {
        /**
         * 直播坐等获取周星数据
         */
        if (mLiveInfo.type == LiveConst.Type.LIVE_AND_MATCH) {
            mViewModel.getWeeklyStarRank()
        }

        mViewModel.launchConsumeUser(mLiveInfo.liveId) //定时5秒请求一次  顶部消费列表
        mViewModel.launchLiveHeartbeat(mLiveInfo.liveId) //心跳

        //试播
        mLiveInfo.trialTime?.also {
            mViewModel.launchTrialCountdown(it)
        }
        //截图
        LiveUtils.resolveScreenshotStrategy(pageType, mScreenshotStrategy)?.also {
            mViewModel.launchScreenshot(pageType, mLiveInfo.liveId, mLiveInfo.startTime, it)
        }
        //开播先认为没有人脸
        triggerFaceChange(valid = false, init = true)

        mPauseLiving = false
    }

    private fun showUserProfilePopup(userId: Long) {
        GlobalPopupManager.showAnchorUserProfilePopup(
            requireContext(),
            this,
            mViewModel,
            userId,
            UserConst.From.LIVE,
            mLiveInfo.liveId,
            mBanMessageUser,
            onMessageClickListener = {
                showChatMessage(it.toUserBasicVo())
            }, onSelectMoreCardListener = {
                showSelectCard(it)
            })
    }

    private fun showSelectCard(infoOtherResp: InfoOtherResp) {
        GlobalPopupManager.showLiveSelectMoreCard(
            requireContext(),
            this,
            mViewModel,
            infoOtherResp,
            mLiveInfo.liveId,
            mLiveInfo.userId,
            mBanMessageUser,
            false,
            mOnKickRoomListener = {
                //踢出房间
                mViewModel.kickUser(infoOtherResp.userId, mLiveInfo.userId)
            },
            onAtClickListener = {
                mBinding.vEdit.atUser(infoOtherResp.userId, infoOtherResp.nickname)
            }
        )
    }

    /**
     * 展示消息列表
     */
    private fun showChatMessage(userBase: UserBasicVo) {
        childFragmentManager.showNewDialogFragment(
            MessageSingleDialogFragment(
                userBase.userId,
                userBase.avatar,
                userBase.avatarFrame,
                userBase.chatBubble,
                nestedPage = false,
                singlePage = true
            ), MessageSessionFragment.FRAGMENT_TAG
        )
    }

    override fun onFaceStateChange(valid: Boolean) {
        withLoaded {
            triggerFaceChange(valid)
        }
    }

    private fun triggerFaceChange(valid: Boolean, init: Boolean = false) {
        if (mPauseLiving) {
            return
        }

        mViewModel.triggerFaceChange(valid, init)
    }

    /**
     * 来电
     */
    override fun onLivingToCall(callBean: CallSignalingMessage) {
        if (isStopLiving()) {
            return
        }

        withLoaded {
            mBinding.avAnswer.onLivingToCall(callBean)
        }
    }

    override fun onCancelToCall(callBean: CallSignalingMessage) {
        withLoaded {
            mBinding.avAnswer.onCancelToCall(callBean)
        }
    }

    override fun onChangeCamera() {
        mOnLiveCallCallback?.onChangeCamera()
    }

    override fun onNetwork(isNetwork: Boolean, isConnected: Boolean) {
        if (mPauseLiving) {
            return
        }

        withLoaded {
            //如果上次是断开连接，这次连接上了，需要重连
            if (!mBinding.vNetwork.isConnected && isConnected) {
                onRecoverLive()
            }

            mBinding.vNetwork.setNetworkState(isNetwork, isConnected)
        }
    }

    override fun onRecoverLive() {
        withLoaded {
            mViewModel.recoverLive()
        }
    }

    override fun setOnLiveCallCallback(l: OnLiveCallCallback) {
        mOnLiveCallCallback = l
    }

    override fun setOnLiveAnswerListener(l: OnLiveAnswerListener) {
        mOnLiveAnswerListener = l
    }

    //停止直播
    private fun onStopLive(needLoading: Boolean = false) {
        if (mStopLive) {
            return
        }
        if (isDestroyView()) {
            return
        }
        mViewModel.stopLive(mLiveInfo.liveId, needLoading)

        mStopLive = true
    }

    private fun isStopLiving(): Boolean {
        //暂停直播或者仅直播不用处理人脸
        return mPauseLiving || mLiveInfo.type == LiveConst.Type.ONLY_LIVE
    }

    /**
     * 更新皮肤
     */
    private fun setSkinUi() {
        val themeData = AppConfigManager.getUserTheme(mLiveInfo.roomTheme)
        mBinding.vFooter.setTheme(themeData)
    }

    override fun onBackPressed(): Boolean {
        if (!isCreated() || activity?.isFinishing != false) {
            return true
        }

        XPopupUtils.showViewPopup(
            LiveHangUpDialog(requireContext(), mLiveInfo.startTime, mLiveInfo.type, mSubsidy) {
                onStopLive(true)
            }.apply {
                autoFragmentHide(this@LiveVideoFragment)
            },
            lifecycle = lifecycle
        )

        return true
    }

    override fun onDestroy() {
        super.onDestroy()

        if (isCreated()) {
            mViewModel.stopKillActivityTimeout()
        }
        EventBus.getDefault().unregister(this)
        AppUtils.unregisterAppStatusChangedListener(onAppStatusChangedListener)
    }

    override fun onDestroyView() {
        super.onDestroyView()

        LiveEngineManage.eventHandlerHelper.removeEventHandler(mEventHandler)
    }

    /**
     * 在后台计时到
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onBackGroundEvent(event: BackgroundEvent) {
        onStopLive()
    }

    companion object {

        private const val pageType = LiveConst.Page.LIVE_ANCHOR

        private const val maxBackgroundTime = 30000L //主播在后台停留挂断事件
    }
}